/*!
 * \file set_relation_dot_visitor_test.cc
 *
 * \brief Set and Relation Dot visitor tests
 *
 * This file is to test the dot visitor of the set and relation classes.
 * Due to the way dot files are set up, there is a debug flag set so that if it
 * is set to true, then it will print out the dot files to standard out. This
 * functionality is to change.
 *
 * \date Started: 6/8/2010
 * \date Last Modified: 7/27/2010
 * \authors Alan LaMielle
 * \authors Ian Craig
 * \authors Nicholas Jeanette
 *
 * Copyright (c) 2010, Colorado State University <br>
 * All rights reserved. <br>
 * See ../../COPYING for details. <br>
 */

#include <iegenlib/iegenlib.h>

#include <gtest/gtest.h>
#include <iostream>
#include <fstream>

#define DEBUG_ALL 0 //Debugging flag

using std::cout;
using std::endl;

using iegenlib::IEGenLibContext;
using iegenlib::Set;
using iegenlib::Relation;
using iegenlib::Symbolic;

//NOTE SHOULD TEST WITH SYMBOLICS

TEST(SRDot, simple1) {
   Set s("{[]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple2) {
   Set s("{[x]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple3) {
   Set s("{[x,y]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple4) {
   Set s("{[1,x]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple5) {
   Set s("{[x,1]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple6) {
   Set s("{[x,y] : x >= 1 and y < x }");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple7) {
   Set s("{[x,y] : x < z}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple8) {
   Set s("{[x,y]: x = y}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simple9) {
   Set s("{[x,y]: x = z and y = z}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}


TEST(SRDot, simple10) {
   Set s("{[1,x]: x > 1}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, dups1) {
   Set s ("{[x,x]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, dups2) {
   Set s("{[x,y,x]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, dups3) {
   Set s("{[x,y,x] : x<y+3}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, dups4) {
   Set s("{[x,y,x] : x = y}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, dups5) {
   Set s("{[x,x,x]}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, exampleFromIssue){
   Set s("{[0,x,x,y] : x < 10  and i > x + y}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function0) {
   Set s("{[x] : f(x)>0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function1) {
   Set s("{[x,y] : f(x,y)=0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function2) {
   Set s("{[x,x] : f(x,x)=0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function3) {
   Set s("{[x,x] : f(x,g(x))=0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function4) {
   Set s("{[x,y] : f(x,1)=0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function5) {
   Set s("{[x,2] : f(x,y)=0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function6) {
   Set s("{[x] : f(1)>0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, function7) {
   Set s("{[x,y] : y=f(x,g(y))}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, functionDuplicateFunctionEqualities) {
   Set s("{[x,2] : f(x,y)=0 and f(x,y)=0}");
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel1) {
   Relation r("{[]->[]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel2) {
   Relation r("{[x]->[x]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel3) {
   Relation r("{[x,y]->[x]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel4) {
   Relation r("{[1,x]->[x,1]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel5) {
   Relation r("{[x,1]->[w,y,z]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel6) {
   Relation r("{[x,y]->[x,y] : x >= 1 and y < x }");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel7) {
   Relation r("{[x,y]->[x,y] : x < z}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, simpleRel8) {
   Relation r("{[x,y]->[x,y]: x = y}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, dupsRel1) {
   Relation r("{[x,x]->[x,x]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, dupsRel2) {
   Relation r("{[x,y,x]->[x,y,x]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, dupsRel3) {
   Relation r("{[x,y,x]->[x,y,x] : x<y+3}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, functionRel0) {
   Relation r("{[x]->[x] : f(x)>0}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, functionRel1) {
   Relation r("{[x,y]->[x,y] : f(x,y)=0}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, functionRel2) {
   Relation r("{[x,x]->[y,y] : f(x,x)=0}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, functionRel3) {
   Relation r("{[x,y]->[x,y] : f(x,1)=0}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, AlanRelation) {
   Relation r("{[a]->[b]:3f(5*g(2a,-5*a)-5)>=0}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, AlanRelation1) {
   Relation r("{[ii] -> [inter_func]: ii>=f(x)}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, AlanRelation2) {
   Relation r("{[a]->[b]:f(g(a,a))>=0}");
    #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, AlanRelation3) {
   Relation r("{[4]->[5]}");
   #if DEBUG_ALL
   cout<<r.get_dot()<<endl;
   #endif
}

TEST(SRDot, Symbolics1){
   IEGenLibContext context;
   context.addSymbolic(Symbolic("z"));
   Set s("{[x,y]: x = z and y = z}", context);
   #if DEBUG_ALL
   cout<<s.get_dot()<<endl;
   #endif
}
